package cn.springBoot.controller;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.dom4j.*;
import org.dom4j.io.SAXReader;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import cn.springBoot.dto.*;

/**
 * @author ljx
 * @description: TODO
 * @class cn.springBoot.controller.ReadXml
 * @create date: 2021/11/18
 */

@RestController
@RequestMapping("/readXml")
public class ReadXml {

    @PostMapping("/readXml")
    public ProcessDfinitionDto readXml(String xmlStr) throws Exception {

        Document document = DocumentHelper.parseText(xmlStr);
        return parseDom4j(document);

    }

    public static ProcessDfinitionDto parseDom4j(Document document) {

        ProcessDfinitionDto process = new ProcessDfinitionDto();
        // 创建一个SAXReader解析器
        SAXReader reader = new SAXReader();

        // 读取xml文件,转换成Document结点
        // Document doc = reader.read(document);

        parseElement(document.getRootElement(), process);

        return process;
    }

    @SuppressWarnings("unchecked")
    public static void parseElement(Element element, ProcessDfinitionDto process) {

        TaskNode taskNode = new TaskNode();

        // 连线
        TaskSequenceFlow flow = new TaskSequenceFlow();

        // 获取节点
        // System.out.println("rootName:" + element.getName());
        // 根节点的属性
        List<Attribute> attrs = element.attributes();
        if (element.getName().equals("process")) {

            // 初始化 因为根节点就出现了一次 所以不会创造多个对象 可以一直存储 避免空指针异常
            process.setTaskNodeList(new ArrayList<TaskNode>());
            process.setTaskSequenceFlowList(new ArrayList<TaskSequenceFlow>());
            process.setDiagramDto(new DiagramDto());

            if (attrs != null) {
                attrs.forEach(attribute -> {
                    if (attribute.getName().equals("id")) {
                        process.setId(attribute.getValue());
                    } else if (attribute.getName().equals("name")) {
                        process.setName(attribute.getValue());
                    }
                });

            }
        }

        if (element.getName().equals("startEvent")) {

            if (attrs != null) {
                attrs.forEach(attribute -> {
                    taskNode.setNodeType("startEvent");
                    if (attribute.getName().equals("id")) {
                        taskNode.setId(attribute.getValue());
                    } else if (attribute.getName().equals("name")) {
                        taskNode.setName(attribute.getValue());
                    }
                });
            }
            process.getTaskNodeList().add(taskNode);
        }

        if (element.getName().equals("endEvent")) {
            if (attrs != null) {
                attrs.forEach(attribute -> {
                    taskNode.setNodeType("endEvent");
                    if (attribute.getName().equals("id")) {
                        taskNode.setId(attribute.getValue());
                    } else if (attribute.getName().equals("name")) {
                        taskNode.setName(attribute.getValue());
                    }
                });
            }
            process.getTaskNodeList().add(taskNode);
        }
        if (element.getName().equals("userTask")) {

            if (attrs != null) {
                attrs.forEach(attribute -> {
                    taskNode.setNodeType("userTask");
                    if (attribute.getName().equals("id")) {
                        taskNode.setId(attribute.getValue());
                    } else if (attribute.getName().equals("name")) {
                        taskNode.setName(attribute.getValue());
                    } else if (attribute.getName().equals("attributeForm")) {

                    }
                });

            }
            process.getTaskNodeList().add(taskNode);
        }
        if (element.getName().equals("serviceTask")) {

            if (attrs != null) {

                attrs.forEach(attribute -> {
                    taskNode.setNodeType("serviceTask");
                    if (attribute.getName().equals("id")) {
                        taskNode.setId(attribute.getValue());
                    } else if (attribute.getName().equals("name")) {
                        taskNode.setName(attribute.getValue());
                    }
                });

            }
            process.getTaskNodeList().add(taskNode);

        }
        if (element.getName().equals("exclusiveGateway")) {

            if (attrs != null) {

                attrs.forEach(attribute -> {

                    taskNode.setNodeType("exclusiveGateway");
                    if (attribute.getName().equals("id")) {
                        taskNode.setId(attribute.getValue());
                    } else if (attribute.getName().equals("name")) {
                        taskNode.setName(attribute.getValue());
                    }
                });

            }
            process.getTaskNodeList().add(taskNode);
        }

        if (element.getName().equals("sequenceFlow")) {

            if (attrs != null) {
                attrs.forEach(attribute -> {
                    if (attribute.getName().equals("id")) {
                        flow.setId(attribute.getValue());
                    } else if (attribute.getName().equals("name")) {
                        flow.setName(attribute.getValue());
                    } else if (attribute.getName().equals("sourceRef")) {
                        flow.setFromId(attribute.getValue());
                    } else if (attribute.getName().equals("targetRef")) {
                        flow.setToId(attribute.getValue());
                    }
                });

            }
            process.getTaskSequenceFlowList().add(flow);
        }

        if (element.getName().equals("BPMNDiagram")) {

            // 同理 初始化 PlaneDto
            process.getDiagramDto().setPlane(new PlaneDto());

            if (attrs != null) {
                attrs.forEach(attribute -> {
                    if (attribute.getName().equals("id")) {
                        process.getDiagramDto().setId(attribute.getValue());
                    }
                });

            }

        }

        if (element.getName().equals("BPMNPlane")) {
            process.getDiagramDto().setPlane(new PlaneDto());
            process.getDiagramDto().getPlane().setEdgeList(new ArrayList<EdgeDto>());
            process.getDiagramDto().getPlane().setShapeList(new ArrayList<ShapeDto>());
            if (attrs != null) {
                attrs.forEach(attribute -> {
                    if (attribute.getName().equals("id")) {

                        process.getDiagramDto().getPlane().setId(attribute.getValue());

                    } else if (attribute.getName().equals("bpmnElement")) {

                        process.getDiagramDto().getPlane().setBpmnElement(attribute.getValue());

                    }
                });

            }

        }

        if (element.getName().equals("BPMNEdge")) {
            EdgeDto dto = new EdgeDto();
            List<WaypointDto> waypointDtosList = new ArrayList<>();
            LabelDto labelDto = new LabelDto();

            if (attrs != null) {
                attrs.forEach(attribute -> {
                    if (attribute.getName().equals("id")) {
                        dto.setId(attribute.getValue());
                    } else if (attribute.getName().equals("bpmnElement")) {
                        dto.setBpmnElement(attribute.getValue());

                    }
                });
            }
            Iterator<Node> iterator = element.nodeIterator();
            while (iterator.hasNext()) {
                Node sonEdgeNode = iterator.next();
                if (sonEdgeNode instanceof Element) {
                    Element sonEdgeELement = (Element)sonEdgeNode;

                    if (sonEdgeELement.getName().equals("waypoint")) {

                        WaypointDto waypointDto = new WaypointDto();

                        List<Attribute> sonEdgeELementAttribute = sonEdgeELement.attributes();

                        if (sonEdgeELementAttribute != null) {
                            sonEdgeELementAttribute.forEach(attribute -> {

                                if (attribute.getName().equals("x")) {
                                    waypointDto.setX(Double.parseDouble(attribute.getValue()));
                                } else if (attribute.getName().equals("y")) {
                                    waypointDto.setY(Double.parseDouble(attribute.getValue()));
                                }
                            });

                        }
                        waypointDtosList.add(waypointDto);
                    } else if (sonEdgeELement.getName().equals("BPMNLabel")) {

                        // 孙子节点
                        Iterator<Node> grandSonIterator = sonEdgeELement.nodeIterator();

                        while (grandSonIterator.hasNext()) {
                            Node grandSonNode = grandSonIterator.next();
                            if (grandSonNode instanceof Element) {
                                Element grandSonElement = (Element)grandSonNode;

                                if (grandSonElement.getName().equals("Bounds")) {
                                    BoundsDto boundsDto = new BoundsDto();
                                    System.out.println(grandSonElement.getName());
                                    List<Attribute> grandSonAttribute = grandSonElement.attributes();

                                    if (grandSonAttribute != null) {
                                        grandSonAttribute.forEach(attribute -> {
                                            if (attribute.getName().equals("x")) {
                                                boundsDto.setX(Double.parseDouble(attribute.getValue()));
                                            } else if (attribute.getName().equals("y")) {
                                                boundsDto.setY(Double.parseDouble(attribute.getValue()));

                                            } else if (attribute.getName().equals("width")) {
                                                boundsDto.setWidth(Double.parseDouble(attribute.getValue()));

                                            } else if (attribute.getName().equals("height")) {
                                                boundsDto.setHeight(Double.parseDouble(attribute.getValue()));

                                            }
                                        });

                                    }
                                    labelDto.setBoundsDto(boundsDto);
                                }
                            }
                        }
                        dto.setLabelDto(labelDto);
                    }

                }
            }

            dto.setWaypointList(waypointDtosList);
            process.getDiagramDto().getPlane().getEdgeList().add(dto);
        }

        if (element.getName().equals("BPMNShape")) {
            ShapeDto shapeDto = new ShapeDto();
            LabelDto labelDto = new LabelDto();
            if (attrs != null) {
                attrs.forEach(attribute -> {
                    if (attribute.getName().equals("id")) {
                        shapeDto.setId(attribute.getValue());
                    } else if (attribute.getName().equals("bpmnElement")) {
                        shapeDto.setBpmnElement(attribute.getValue());
                    }
                });
            }
            // 子节点
            Iterator<Node> iterator = element.nodeIterator();
            while (iterator.hasNext()) {
                Node sonNode = iterator.next();
                if (sonNode instanceof Element) {
                    Element sonElement = (Element)sonNode;

                    if (sonElement.getName().equals("Bounds")) {
                        BoundsDto boundsDto = new BoundsDto();
                        List<Attribute> sonAttribute = sonElement.attributes();

                        if (sonAttribute != null) {
                            sonAttribute.forEach(attribute -> {

                                if (attribute.getName().equals("x")) {
                                    boundsDto.setX(Double.parseDouble(attribute.getValue()));
                                } else if (attribute.getName().equals("y")) {
                                    boundsDto.setY(Double.parseDouble(attribute.getValue()));

                                } else if (attribute.getName().equals("width")) {
                                    boundsDto.setWidth(Double.parseDouble(attribute.getValue()));

                                } else if (attribute.getName().equals("height")) {
                                    boundsDto.setHeight(Double.parseDouble(attribute.getValue()));

                                }
                            });

                        }
                        shapeDto.setBounds(boundsDto);

                    }
                    if (sonElement.getName().equals("BPMNLabel")) {

                        BoundsDto boundsDto = new BoundsDto();

                        // 子节点
                        Iterator<Node> grandSonIterator = element.nodeIterator();

                        while (grandSonIterator.hasNext()) {
                            Node grandSonNode = grandSonIterator.next();
                            if (grandSonNode instanceof Element) {
                                Element grandSonElement = (Element)grandSonNode;

                                if (grandSonElement.getName().equals("Bounds")) {

                                    List<Attribute> grandSonAttribute = grandSonElement.attributes();

                                    if (grandSonAttribute != null) {
                                        grandSonAttribute.forEach(attribute -> {
                                            if (attribute.getName().equals("x")) {
                                                boundsDto.setX(Double.parseDouble(attribute.getValue()));
                                            } else if (attribute.getName().equals("y")) {
                                                boundsDto.setY(Double.parseDouble(attribute.getValue()));

                                            } else if (attribute.getName().equals("width")) {
                                                boundsDto.setWidth(Double.parseDouble(attribute.getValue()));

                                            } else if (attribute.getName().equals("height")) {
                                                boundsDto.setHeight(Double.parseDouble(attribute.getValue()));

                                            }

                                        });

                                    }
                                    labelDto.setBoundsDto(boundsDto);
                                }
                            }

                        }

                        shapeDto.setLabelDto(labelDto);

                    }

                }

            }

            process.getDiagramDto().getPlane().getShapeList().add(shapeDto);
        }

        // 子节点
        Iterator<Node> iterator = element.nodeIterator();
        while (iterator.hasNext()) {
            Node node = iterator.next();
            if (node instanceof Element) {
                Element eleNode = (Element)node;
                parseElement(eleNode, process);
            }
            /*if (node instanceof Text) {
                Text text = (Text) node;
                process.append(text.getText());
            }
            if (node instanceof CDATA) {
                CDATA dataNode = (CDATA) node;
                buffer.append(dataNode.getText());
            }
            if (node instanceof Comment) {
                Comment comNode = (Comment) node;
                buffer.append(comNode.getText());
            }*/
        }

    }

}
